//
#include "common.hpp"
#include "fs.hpp"
#include <ctime>

namespace gitee {
constexpr size_t TIME_LENGTH = 16;

inline gitee::string_view PathRemoveSpecSuffix(gitee::string_view sv) {
  auto pos = sv.find_last_not_of('/');
  if (pos == gitee::string_view::npos) {
    return "/";
  }
  auto n = sv.size() - pos - 1;
  if (n > 0) {
    sv.remove_suffix(n);
  }
  return sv;
}

inline bool TimeNow(char *buf) {
  auto t = time(nullptr);
  struct tm tm_;
  localtime_r(&t, &tm_);
  snprintf(buf, TIME_LENGTH, "%04d-%02d-%02d", (tm_.tm_year + 1900),
           (tm_.tm_mon + 1), tm_.tm_mday);
  return true;
}

char *simple_itoa(char *p, uint32_t x) {
  // number of digits in a uint32_t + NUL
  p += 11;
  *--p = 0;
  do {
    *--p = '0' + x % 10;
    x /= 10;
  } while (x);
  return p;
}

bool RenameSecure(gitee::string_view to) {
  auto rdX = gitee::StrCat(to, ".10");
  if (gitee::PathDirExists(rdX.data())) {
    // --remove this dir
    if (!gitee::RecurseRmdir(rdX)) {
      return false;
    }
  }
  char digits[32];
  // example
  // /home/git/repositories/trash/2019-09-11/ex/example/hello.git.9
  // rename to /home/git/repositories/trash/2019-09-11/ex/example/hello.git.10
  for (uint32_t i = 9; i > 0; i--) {
    auto rdTo = gitee::StrCat(to, ".", simple_itoa(digits, i + 1));
    auto rdFrom = gitee::StrCat(to, ".", simple_itoa(digits, i));
    rename(rdFrom.data(), rdTo.data());
  }
  auto rd = gitee::StrCat(to, ".1");
  return rename(to.data(), rd.data()) == 0;
}

// RenameEx
bool RenameEx(gitee::string_view from, gitee::string_view to) {
  if (gitee::PathDirExists(to.data()) && !RenameSecure(to)) {
    return false;
  }
  return rename(from.data(), to.data()) == 0;
}

bool MoveRepoToTrashEx(gitee::string_view root, gitee::string_view trash,
                       gitee::string_view diskpath, std::string &trashdir) {
  root = PathRemoveSpecSuffix(root);
  trash = PathRemoveSpecSuffix(trash);
  diskpath = PathRemoveSpecSuffix(diskpath);
  // -------> parse
  auto path = gitee::StrCat(root, "/", diskpath, ".git");
  auto wikipath = gitee::StrCat(root, "/", gitee::StripSuffix(diskpath, ".git"),
                                ".wiki.git");

  char timenow[TIME_LENGTH];
  TimeNow(timenow);
  trashdir = gitee::StrCat(trash, "/", timenow, "/", diskpath, ".git");
  auto trashbasedir = gitee::DirName(trashdir);
  if (!gitee::MakeDirRecurseFullPath(trashbasedir)) {
    /// unable mkdir recurse..
    return false;
  }
  auto wikitrashdir =
      gitee::StrCat(trash, "/", timenow, "/", diskpath, ".wiki.git");

  RenameEx(wikipath, wikitrashdir);
  return RenameEx(path, trashdir);
}
} // namespace gitee
